* misc improvements.
fix memory leak in nmea reader.
eliminate extra string conversion using xml_parse_time.
use local QByteArray instead of xstrdup.
convert human_to_dec interface to QString.
* use strtod to track converted len in human_to_dec.
* enhance humantodec test.
*/
#include <cassert> // for assert
-#include <cctype> // for isspace
#include <cmath> // for fabs
-#include <cstdio> // for size_t
#include <cstdlib> // for atof, strtod
#include <cstring> // for strlen, strchr, strncmp, strcmp, memmove, strcpy, strcspn, strncpy
+#include <QByteArray> // for QByteArray
#include <QChar> // for QChar
#include <QDebug> // for QDebug
#include <QRegularExpression> // for QRegularExpression
/*****************************************************************************
* human_to_dec() - convert a "human-readable" lat and/or lon to decimal
- * usage: human_to_dec( "N 41� 09.12' W 085� 09.36'", &lat, &lon );
+ * usage: human_to_dec( "N 41° 09.12′ W 085° 09.36′", &lat, &lon );
* human_to_dec( "41 9 5.652 N", &lat, &lon );
*
* which: 0-no preference 1-prefer lat 2-prefer lon
*****************************************************************************/
void
-human_to_dec(const char* instr, double* outlat, double* outlon, int which)
+human_to_dec(const QString& instr, double* outlat, double* outlon, int which)
{
double unk[3] = {999,999,999};
double lat[3] = {999,999,999};
int lonsign = 0;
int unksign = 1;
- const char* cur;
double* numres = unk;
int numind = 0;
- char* buff = nullptr;
- if (strchr(instr, ',') != nullptr) {
- char* c;
- buff = xstrdup(instr);
- while ((c = strchr(buff, ','))) {
- *c = '.';
- }
- cur = buff;
- } else {
- cur = instr;
- }
+ // Allow comma as decimal separator.
+ const QByteArray inbytes = instr.toUtf8().replace(',', '.');
+ const char* cur = inbytes.constData();
while (cur && *cur) {
switch (*cur) {
case '9':
case '0':
case '.':
- case ',':
- numres[numind] = atof(cur);
- while (cur && *cur && strchr("1234567890.,",*cur)) {
- cur++;
- }
+ char* end;
+ numres[numind] = strtod(cur, &end);
+ cur = end;
break;
case '-':
unksign = -1;
*outlon *= lonsign;
}
}
- if (buff) {
- xfree(buff);
- }
}
/*
ddmmdir_to_degrees(const char* ddmmdir);
void
-human_to_dec(const char* instr, double* outlat, double* outlon, int which);
-inline void
-human_to_dec(const QString& instr, double* outlat, double* outlon, int which) {
- human_to_dec(CSTR(instr), outlat, outlon, which);
-}
+human_to_dec(const QString& instr, double* outlat, double* outlon, int which);
QString
dec_to_human(const char* format, const char* dirs, double val);
int off_hr = 0;
int off_min = 0;
int off_sign = 1;
- char* timestr = xstrdup(dateTimeString);
+
+ QByteArray dts = dateTimeString.toUtf8();
+ char* timestr = dts.data();
char* offsetstr = strchr(timestr, 'Z');
if (offsetstr) {
} else {
dt = QDateTime();
}
- xfree(timestr);
return dt;
}
break;
}
+ nmea_release_wpt(curr_waypt);
+ curr_waypt = nullptr;
+
posn_fname.clear();
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx version="1.0" creator="GPSBabel - https://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/0">
+ <time>1970-01-01T00:00:00Z</time>
+ <bounds minlat="-1.234000000" minlon="-5.678000000" maxlat="-1.234000000" maxlon="-5.678000000"/>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point0</name>
+ <cmt>point0</cmt>
+ <desc>point0</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point1</name>
+ <cmt>point1</cmt>
+ <desc>point1</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point2</name>
+ <cmt>point2</cmt>
+ <desc>point2</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point3</name>
+ <cmt>point3</cmt>
+ <desc>point3</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point4</name>
+ <cmt>point4</cmt>
+ <desc>point4</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point5</name>
+ <cmt>point5</cmt>
+ <desc>point5</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point6</name>
+ <cmt>point6</cmt>
+ <desc>point6</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point7</name>
+ <cmt>point7</cmt>
+ <desc>point7</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point8</name>
+ <cmt>point8</cmt>
+ <desc>point8</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point9</name>
+ <cmt>point9</cmt>
+ <desc>point9</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point10</name>
+ <cmt>point10</cmt>
+ <desc>point10</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point11</name>
+ <cmt>point11</cmt>
+ <desc>point11</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point12</name>
+ <cmt>point12</cmt>
+ <desc>point12</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point13</name>
+ <cmt>point13</cmt>
+ <desc>point13</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point14</name>
+ <cmt>point14</cmt>
+ <desc>point14</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point15</name>
+ <cmt>point15</cmt>
+ <desc>point15</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point16</name>
+ <cmt>point16</cmt>
+ <desc>point16</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point17</name>
+ <cmt>point17</cmt>
+ <desc>point17</desc>
+ </wpt>
+ <wpt lat="-1.234000000" lon="-5.678000000">
+ <name>point18</name>
+ <cmt>point18</cmt>
+ <desc>point18</desc>
+ </wpt>
+</gpx>
--- /dev/null
+lat,lon,desc
+1.234°S,5.678°W,point0
+1°14.04′S,5°40.68′W,point1
+1°14′2.4″S,5°40′40.8″W,point2
+S1.234°,W5.678°,point3
+S1°14.04′,W5°40.68′,point4
+S1°14′2.4″,W5°40′40.8″,point5
+-1.234°,-5.678°,point6
+-1°14.04′,-5°40.68′,point7
+-1°14′2.4″,-5°40′40.8″,point8
+1.234° S,5.678° W,point9
+1° 14.04′ S,5° 40.68′ W,point10
+1° 14′ 2.4″ S,5° 40′ 40.8″ W,point11
+S 1.234°,W 5.678°,point12
+S 1° 14.04′,W 5° 40.68′,point13
+S 1° 14′ 2.4″,W 5° 40′ 40.8″,point14
+-1.234°,-5.678°,point15
+-1° 14.04′,-5° 40.68′,point16
+-1° 14′ 2.4″,-5° 40′ 40.8″,point17
+-1.234,-5.678,point18
--- /dev/null
+lat lon desc
+1,234°S 5,678°W point0
+1°14,04′S 5°40,68′W point1
+1°14′2,4″S 5°40′40,8″W point2
+S1,234° W5,678° point3
+S1°14,04′ W5°40,68′ point4
+S1°14′2,4″ W5°40′40,8″ point5
+-1,234° -5,678° point6
+-1°14,04′ -5°40,68′ point7
+-1°14′2,4″ -5°40′40,8″ point8
+1,234° S 5,678° W point9
+1° 14,04′ S 5° 40,68′ W point10
+1° 14′ 2,4″ S 5° 40′ 40,8″ W point11
+S 1,234° W 5,678° point12
+S 1° 14,04′ W 5° 40,68′ point13
+S 1° 14′ 2,4″ W 5° 40′ 40,8″ point14
+-1,234° -5,678° point15
+-1° 14,04′ -5° 40,68′ point16
+-1° 14′ 2,4″ -5° 40′ 40,8″ point17
+-1,234 -5,678 point18
gpsbabel -i unicsv -f ${REFERENCE}/libreoffice.csv -o unicsv -F ${TMPDIR}/libreoffice2.csv
gpsbabel -i unicsv -f ${TMPDIR}/libreoffice2.csv -o text,degformat=ddd -F ${TMPDIR}/libreoffice2.text
compare ${REFERENCE}/libreoffice.text ${TMPDIR}/libreoffice2.text
+
+gpsbabel -i unicsv -f ${REFERENCE}/humantodec1.csv -o gpx -F ${TMPDIR}/humantodec1.gpx
+compare ${REFERENCE}/humantodec.gpx ${TMPDIR}/humantodec1.gpx
+gpsbabel -i unicsv -f ${REFERENCE}/humantodec2.csv -o gpx -F ${TMPDIR}/humantodec2.gpx
+compare ${REFERENCE}/humantodec.gpx ${TMPDIR}/humantodec2.gpx
wpt->latitude = intdeg_to_dec((int) atof(s));
break;
case XcsvStyle::XT_LAT_HUMAN_READABLE:
- human_to_dec(s, &wpt->latitude, &wpt->longitude, 1);
+ human_to_dec(value, &wpt->latitude, &wpt->longitude, 1);
break;
case XcsvStyle::XT_LAT_DDMMDIR:
wpt->latitude = ddmmdir_to_degrees(s);
wpt->longitude = intdeg_to_dec((int) atof(s));
break;
case XcsvStyle::XT_LON_HUMAN_READABLE:
- human_to_dec(s, &wpt->latitude, &wpt->longitude, 2);
+ human_to_dec(value, &wpt->latitude, &wpt->longitude, 2);
break;
case XcsvStyle::XT_LON_DDMMDIR:
wpt->longitude = ddmmdir_to_degrees(s);
// case XcsvStyle::XT_LON_10E is handled outside the switch.
/* LAT AND LON CONVERSIONS ********************************************/
case XcsvStyle::XT_LATLON_HUMAN_READABLE:
- human_to_dec(s, &wpt->latitude, &wpt->longitude, 0);
+ human_to_dec(value, &wpt->latitude, &wpt->longitude, 0);
break;
/* DIRECTIONS **********************************************************/
case XcsvStyle::XT_LAT_DIR:
break;
case XcsvStyle::XT_ISO_TIME:
case XcsvStyle::XT_ISO_TIME_MS:
- wpt->SetCreationTime(xml_parse_time(s));
+ wpt->SetCreationTime(xml_parse_time(value));
break;
case XcsvStyle::XT_NET_TIME: {
bool ok;